View Javadoc

1   /*
2    * BasicMappingAuthZService.java
3    *
4    */
5   
6   package org.opensciencegrid.authz.service;
7   
8   import java.net.InetAddress;
9   import java.util.ArrayList;
10  import java.util.Iterator;
11  
12  
13  import org.opensaml.v1_0_1.SAMLSubject;
14  import org.opensaml.v1_0_1.SAMLException;
15  import org.opensaml.v1_0_1.SAMLAction;
16  import org.opensaml.v1_0_1.SAMLDecision;
17  
18  import org.opensciencegrid.authz.saml.XACMLObligation;
19  import org.opensciencegrid.authz.common.OSGAuthorizationConstants;
20  import org.opensciencegrid.authz.common.GridId;
21  import org.opensciencegrid.authz.common.LocalId;
22  
23  import org.apache.log4j.Category;
24  
25  /*** Implements the SAML AuthZ service as a simple mapping service.
26   * Receives a SAML authorization requests and queries a GRID Identity
27   * Mapping Service to decide how to perform the GRID identity to local
28   * identity mapping.
29   *
30   * @author Markus Lorch, Gabriele Carcassi
31   */
32  public class BasicMappingAuthZService extends SAMLAuthZServiceBase {
33  
34      //##########################################################################################
35      // Members
36  
37      /*** the mapService used to perform the identity mapping*/
38      GRIDIdentityMappingService mapService;
39  
40      /*** the identity/name/dn of this service */
41      protected String serviceIdentity = "Basic Mapping AuthZ Service (give me a name!)";
42      
43      /*** Log4Java logger */
44      static Category log = Category.getInstance(BasicMappingAuthZService.class.getName() );
45  
46      //##########################################################################################
47      // Methods
48  
49      /*** Creates a SAML AuthZ service from a GRID Identity Mapping Service.*/
50      public BasicMappingAuthZService(GRIDIdentityMappingService mapService) {
51          this.mapService = mapService;
52          try {
53              serviceIdentity = InetAddress.getLocalHost().getHostName();
54          } catch (Exception e) {
55              log.warn("Couldn't retrieve local host. Setting default server identity.");
56              serviceIdentity = "Basic Mapping AuthZ Service";
57          }
58      }
59  
60  
61      /*** the main method, it implements the abstract authorize method with 
62       * the logic necessary to make an identity mapping decision and interfaces
63       * with the identity mapping service
64       * the function interprets the responses from the mappingservice mapCredentials
65       * function as follows:
66       * mapCredentials returns LocalId object = permit
67       * mapCredentials returns null = deny
68       * mapCredentials throws exception = indeterminate
69       * if any of the other functions fail the result will also be indeterminate or,
70       * an exception will be thrown
71       * provides an AuthzDecision object which contains a decision, permitted actions, 
72       * obligations and the issuer name (the name of this service) 
73       */
74  
75      protected AuthzDecision authorize(SAMLSubject subject, String resource, Iterator actions, Iterator evidence) 
76        throws SAMLException {
77  
78          log.debug("entered authorize method of: " + serviceIdentity);
79  
80          AuthzDecision response = new AuthzDecision();
81  
82          // who are we - the serviceIdentity needs to be properly set
83          response.issuer=serviceIdentity;
84  
85          // this is the only action we support and provide a permit response for
86          ArrayList permissibleActions = new ArrayList(1);
87          permissibleActions.add(new SAMLAction(OSGAuthorizationConstants.AUTHZ_NS, 
88                                                OSGAuthorizationConstants.ACCESS_AS_LOCAL_ID) );
89          log.debug("This service supports only the following action: "+OSGAuthorizationConstants.ACCESS_AS_LOCAL_ID);
90  
91          // check if requested action is supported, else return INDETERMINATE
92          if((response.actions=locatePermissibleActions(actions, permissibleActions))!=null) {       
93   
94            //found at least one permissible action (the MAPPING_REQUEST_ACTION is the only one), so go on
95            log.debug("Supported action is requested");
96         
97            // extract FQAN - VOMS attribute if present
98            log.debug("Checking if VOMS attribute (FQAN) is present in Subject Evidence");
99            FQAN fqan = findFQANinSubjectEvidence(evidence, subject);
100           if(fqan!=null) log.debug("found VOMS attribute with data \""+fqan.data+"\" from \""+fqan.issuer+"\"");
101           else log.debug("no VOMS attribute found in Subject evidence");
102  
103           // create and populate grid identity object
104           GridId gridID = new GridId();
105           gridID.setUserDN(subject.getName().getName());
106           gridID.setHostDN(resource);
107           if(fqan!=null) {
108             gridID.setUserFQAN(fqan.data);
109             gridID.setUserFQANIssuer(fqan.issuer);
110           }
111 
112           // retrieve a local id object from the mapping service
113           log.debug("Request mapping from mapping service");
114           LocalId localID = mapService.mapCredentials(gridID);
115  
116           // check if decision is going to be positive
117           if(localID!=null) { 
118             log.debug("Received PERMIT decision from mapping service");
119             response.decision = SAMLDecision.PERMIT;
120          
121             // add obligations based on ID
122             response.obligations = createObligations(localID);
123 
124           } // end if localID!=null
125           else {
126             // no localID object was returned, so we need to deny access
127             log.debug("Received DENY decision from mapping service");
128             response.decision = SAMLDecision.DENY;
129           }
130 
131         } // end if mappingActionPresent        
132         else {
133           // return indeterminate, mapping action was not present (wrong question asked)
134           log.debug("No supported action was requested, responding with indeterminate");
135           response.decision = SAMLDecision.INDETERMINATE;   
136           log.debug("Setting actions to mapping action, obligations to null");
137           response.actions = new ArrayList(1);
138           response.actions.add(new SAMLAction(OSGAuthorizationConstants.AUTHZ_NS,
139                                               OSGAuthorizationConstants.ACCESS_AS_LOCAL_ID) );
140           response.obligations=null;
141         }
142 
143 
144         return response;
145 
146     } // end authorize method
147 
148 
149    /*** creates corresponding OSG XACML obligations based on the 
150     *  fields that are holding values in the localID object */ 
151 
152    private ArrayList createObligations(LocalId localID) 
153      throws SAMLException {
154  
155     ArrayList oblig = new ArrayList();
156     String tmp;
157 
158     // user name
159     if((tmp=localID.getUserName())!=null)
160               oblig.add(new XACMLObligation(OSGAuthorizationConstants.USERIDOBLIGATION,
161 				            SAMLDecision.PERMIT,
162                                             OSGAuthorizationConstants.USERIDATTRIBUTE,
163                                             OSGAuthorizationConstants.STRINGDATATYPE,
164                                             tmp));
165     // group name
166     if((tmp=localID.getGroupName())!=null)
167               oblig.add(new XACMLObligation(OSGAuthorizationConstants.GROUPIDOBLIGATION,
168 				            SAMLDecision.PERMIT,
169                                             OSGAuthorizationConstants.GROUPIDATTRIBUTE,
170                                             OSGAuthorizationConstants.STRINGDATATYPE,
171                                             tmp));
172     // supplementalGroupNames
173     String [] tmp2;
174     if((tmp2=localID.getSupplementalGroupNames())!=null) {
175               // put all the suppl. groups into one string, separated by a space
176               tmp = tmp2[0];
177               for(int i=1; i<tmp2.length; i++) 
178                  tmp.concat(" "+tmp2[i]);
179               oblig.add(new XACMLObligation(OSGAuthorizationConstants.SUPGROUPIDSOBLIGATION,
180 				            SAMLDecision.PERMIT,
181                                             OSGAuthorizationConstants.SUPGROUPIDSATTRIBUTE,
182                                             OSGAuthorizationConstants.STRINGDATATYPE,
183                                             tmp));
184     } // end if
185     // rootPath
186     if((tmp=localID.getRootPath())!=null)
187               oblig.add(new XACMLObligation(OSGAuthorizationConstants.ROOTPATHOBLIGATION,
188 				            SAMLDecision.PERMIT,
189                                             OSGAuthorizationConstants.ROOTPATHATTRIBUTE,
190                                             OSGAuthorizationConstants.STRINGDATATYPE,
191                                             tmp));
192 
193     // relativeHomePath
194     if((tmp=localID.getRelativeHomePath())!=null)
195               oblig.add(new XACMLObligation(OSGAuthorizationConstants.RELHOMEPATHOBLIGATION,
196 				            SAMLDecision.PERMIT,
197                                             OSGAuthorizationConstants.RELHOMEPATHATTRIBUTE,
198                                             OSGAuthorizationConstants.STRINGDATATYPE,
199                                             tmp));
200 
201   
202    if (oblig.isEmpty()) return null;
203    return oblig;
204    } // end method
205 
206 
207 } // end class